package com.gitee.chili.leisure.util;

import org.springframework.util.LinkedMultiValueMap;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * MultiValueConcurrentHashMap
 *
 * 线程安全的方式
 *
 * @author week solider
 * @since 2020-07-29
 */
public class MultiValueConcurrentHashMap<K, V> extends MultiValueMapAdapter<K, V> {

    /**
     * Create a new LinkedMultiValueMap that wraps a {@link ConcurrentHashMap}.
     */
    public MultiValueConcurrentHashMap() {
        super(new ConcurrentHashMap<>());
    }

    /**
     * Create a new LinkedMultiValueMap that wraps a {@link ConcurrentHashMap}
     * with the given initial capacity.
     * @param initialCapacity the initial capacity
     */
    public MultiValueConcurrentHashMap(int initialCapacity) {
        super(new ConcurrentHashMap<>(initialCapacity));
    }

    /**
     * Copy constructor: Create a new LinkedMultiValueMap with the same mappings as
     * the specified Map. Note that this will be a shallow copy; its value-holding
     * List entries will get reused and therefore cannot get modified independently.
     * @param otherMap the Map whose mappings are to be placed in this Map
     * @see #clone()
     * @see #deepCopy()
     */
    public MultiValueConcurrentHashMap(Map<K, List<V>> otherMap) {
        super(new ConcurrentHashMap<>(otherMap));
    }


    /**
     * Create a deep copy of this Map.
     * @return a copy of this Map, including a copy of each value-holding List entry
     * (consistently using an independent modifiable {@link CopyOnWriteArrayList} for each entry)
     * along the lines of {@code MultiValueMap.addAll} semantics
     * @since 4.2
     * @see #addAll(org.springframework.util.MultiValueMap)
     * @see #clone()
     */
    public MultiValueConcurrentHashMap<K, V> deepCopy() {
        MultiValueConcurrentHashMap<K, V> copy = new MultiValueConcurrentHashMap<>(size());
        forEach((key, values) -> copy.put(key, new CopyOnWriteArrayList<>(values)));
        return copy;
    }

    /**
     * Create a regular copy of this Map.
     * @return a shallow copy of this Map, reusing this Map's value-holding List entries
     * (even if some entries are shared or unmodifiable) along the lines of standard
     * {@code Map.put} semantics
     * @since 4.2
     * @see #put(Object, List)
     * @see #putAll(Map)
     * @see LinkedMultiValueMap#LinkedMultiValueMap(Map)
     * @see #deepCopy()
     */
    @Override
    public MultiValueConcurrentHashMap<K, V> clone() {
        return new MultiValueConcurrentHashMap<>(this);
    }

}
